/*  -*- mode: c++; coding: utf-8; c-file-style: "stroustrup"; -*-

    Copyright 2008 Asier Aguirre <asier.aguirre@gmail.com>
    This file is part of Intromit.

    Intromit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Intromit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Intromit.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef READCOMMAND_HH
#define READCOMMAND_HH
//! \addtogroup python_embed_backend
//@{

#include <pthread.h>
#include <stdio.h>

// TYPEDEFS

//! Command specification as used by readcommand
typedef struct command
{
    const char *name;
    int (*function)(int n_param, char **param, void *ctx);
    // return -1 on error, -2 on ok, -3 for help
    const char *proto;
} command_struct;

// CLASS

//! Readline interface with command parsing, completion and other features
class readcommand
{
    pthread_t *thread;
    int thread_force_end;
    int executing;
    int save_history;
    char **command_fifo;  // fifo commands
    int cf_set, cf_get;   // command fifo pointers
    char *prompt, *history_file;

    char **(*completion_user)(const char *text, int start, int end, char *complete_text, void *data);
    void *completion_user_data;
    char **completion_user_provided;

    // ** PRIVATE FUNCTIONS **
    void ctor();
    void dtor();
    void kill_thread();
    static void *thread_main_static(readcommand *);
    void *thread_main();
    static int event_hook_static();
    int event_hook();
    static int getc_func(FILE *);
    void set_prompt(const char *prompt);

    static char **completion_static(const char *text, int start, int end);
    char **completion(const char *text, int start, int end);
    static char *from_completion_user_provided_generator(const char *text, int state);

    // command list functions
    static command_struct *command_list;
    static void *command_list_ctx;

public:
    readcommand();
    ~readcommand();

    int init(const char *prompt=NULL, const char *history_file=NULL);

    // read a command if any (if NULL, thread ended)
    // returned pointer is volatile, dont free it
    char *command();

    // user completion callback
    // the function should return a NULL terminated array of strings that will be freed by this class
    int set_completion(char **(*comp)(const char *text, int start, int end, char *complete_text, void *data), void *comp_data);

    // do not save history at exit
    inline void do_not_save_history() {save_history=0;}

    // command list
    int command_list_start(command_struct *command_list, void *ctx);
    int command_list_execution(char *command=NULL);
    static int command_list_help(int n_param, char **param, void *ctx);
    static char **command_list_completion(const char *text, int start, int end, char *complete_text, void *obj);
};

//@}
#endif

/* Offline metadata attributes:

   @metadata_attrs(
	command,
	command_struct,
	readcommand_empty_string,
	readcommand_singleton,
	readcommand:
					~select
   )
*/
